﻿using System.Net;
using System.Text.Json;
using Flurl.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using ORS.OrderRobot.IOC;
using ORS.OrderRobot.ServiceContracts;
using ORS.OrderRobot.ServiceContracts.Dtos;


public class HttpHelper : IHttpHelper, ISingleton
{
    private readonly IServiceProvider _serviceProvider;
    public HttpHelper(IServiceProvider  serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public async Task<ResponseInfo<string>> SendAsync(string url, HttpMethod method, RequestInfo? requestInfo = null)
    {
        using var scope = _serviceProvider.CreateScope();
        var _proxyPool = scope.ServiceProvider.GetRequiredService<IProxyPool>();
        var _logger = scope.ServiceProvider.GetRequiredService<ILogger<HttpHelper>>();
        var _systemConfigService = scope.ServiceProvider.GetRequiredService<ISystemConfigService>();

        var proxyInfo = _proxyPool?.GetNextProxy();
        var requestOption = requestInfo ?? new RequestInfo();
        var handler = new HttpClientHandler();
        if (proxyInfo != null)
        {
            var webProxy = new WebProxy(proxyInfo.Host, proxyInfo.Port);
            if (!string.IsNullOrWhiteSpace(proxyInfo.Username) && !string.IsNullOrWhiteSpace(proxyInfo.Password))
            {
                webProxy.Credentials = new NetworkCredential(proxyInfo.Username, proxyInfo.Password);
            }

            handler.Proxy = webProxy;
            handler.UseProxy = true;
        }
        var configDto = await _systemConfigService.GetConfigAsync();
        var addressUrl = url;
        if (!url.StartsWith("http", StringComparison.OrdinalIgnoreCase))
        {
            var pathStr = url.StartsWith("/") ? url : $"/{url}";
            addressUrl = $"{configDto.ApiGateway}{pathStr}";
        }
        var restClient = new FlurlClient(new HttpClient(handler));
        var request = restClient.Request(addressUrl).WithTimeout(TimeSpan.FromMinutes(5));

        if (!string.IsNullOrWhiteSpace(requestOption.BearerToken))
        {
            request = request.WithOAuthBearerToken(requestInfo.BearerToken);
        }
        if (requestOption.Headers != null && requestOption.Headers.Any())
        {
            foreach (var kv in requestOption.Headers)
                request = request.WithHeader(kv.Key, kv.Value);
        }
        if(!url.StartsWith("http", StringComparison.OrdinalIgnoreCase)){
            request = request.SetQueryParam("client_id", configDto.ApiParamClientId).SetQueryParam("locale", "zh-CN");
        }
        if (requestOption.Params != null && requestOption.Params.Any())
        {
            foreach (var kv in requestOption.Params)
                request = request.SetQueryParam(kv.Key, kv.Value);
        }

        //_logger.LogInformation("HTTP {Method} 请求: {Url}", method, request.Url.ToString());

        try
        {
            IFlurlResponse response = method switch
            {
                var m when m == HttpMethod.Get => await request.AllowAnyHttpStatus().GetAsync(),
                var m when m == HttpMethod.Post => await request.AllowAnyHttpStatus().PostJsonAsync(requestOption.Body),
                var m when m == HttpMethod.Put => await request.AllowAnyHttpStatus().PutJsonAsync(requestOption.Body),
                var m when m == HttpMethod.Patch => await request.AllowAnyHttpStatus().PatchJsonAsync(requestOption.Body),
                var m when m == HttpMethod.Delete => await request.AllowAnyHttpStatus().DeleteAsync(),
                var m when m == HttpMethod.Head => await request.AllowAnyHttpStatus().HeadAsync(),
                _ => throw new NotSupportedException($"不支持的 HTTP 方法: {method}")

            };

            var content = await response.GetStringAsync();
            var headers = response.Headers.GroupBy(x => x.Name).ToDictionary(g => g.Key, g => g.First().Value);
            var statusCode = response.StatusCode;
            if (statusCode != 200 && requestInfo?.DisableErrLog != true)
            {
                _logger.LogError("HTTP {Method} 请求：{Url}\n状态码:{statusCode}\n入参{request}\n响应:{content}", method, request.Url.ToString(), statusCode, JsonSerializer.Serialize(requestInfo.Body), content);
            }
            return new ResponseInfo<string>
            {
                StatusCode = response.StatusCode,
                Headers = headers,
                Body = content,
                RawContent = content
            };
        }
        catch (FlurlHttpTimeoutException ex)
        {
            _logger.LogError(ex, "HTTP 请求超时: {Url}", addressUrl);
            return new ResponseInfo<string>
            {
                StatusCode = 408, // 408 Request Timeout
                Headers = new Dictionary<string, string>(),
                Body = string.Empty,
                RawContent = "请求超时"
            };
        }
        catch (TaskCanceledException ex)
        {
            _logger.LogError(ex, "HTTP 请求被取消（可能超时）: {Url}", addressUrl);
            return new ResponseInfo<string>
            {
                StatusCode = 499, // 非标准，代表客户端取消（如手动取消、超时）
                Headers = new Dictionary<string, string>(),
                Body = string.Empty,
                RawContent = "请求取消/超时"
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "HTTP 请求异常: {Url}", addressUrl);
            return new ResponseInfo<string>
            {
                StatusCode = 500,
                Headers = new Dictionary<string, string>(),
                Body = string.Empty,
                RawContent = ex.Message
            };
        }
    }

    public async Task<ResponseInfo<T>> SendAndParseAsync<T>(string url, HttpMethod method, RequestInfo? requestInfo = null)
    {
        using var scope = _serviceProvider.CreateScope();
        var _logger = scope.ServiceProvider.GetRequiredService<ILogger<HttpHelper>>();

        var responseInfo = await SendAsync(url, method, requestInfo);
        if (responseInfo.StatusCode != 200)
        {
            return new ResponseInfo<T>
            {
                Headers = responseInfo.Headers,
                StatusCode = responseInfo.StatusCode,
                Body = default(T),
                RawContent = responseInfo.RawContent,
            };
        }
        try
        {
            var body =  JsonSerializer.Deserialize<T>(responseInfo.Body, new JsonSerializerOptions
            {
                PropertyNameCaseInsensitive = true
            }) ?? throw new JsonException("反序列化返回了 null");
            return new ResponseInfo<T>{
                Headers = responseInfo.Headers,
                StatusCode = responseInfo.StatusCode,
                Body = body,
                RawContent = responseInfo.RawContent,
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "http请求反序列化失败: {Content}", responseInfo.Body);
            throw;
        }
    }
}
